home *** CD-ROM | disk | FTP | other *** search
- // $Id: strings.C,v 1.4 92/01/09 11:26:01 dag Exp $
- //
- // NOTE: internal_buffer_size > 1 required by operator = (char).
-
-
- #include <defs.H>
- #include <strings.H>
- #include <ctype.h>
- #include <iostream.h>
-
-
- // Set DO_STAT true to collect statistics on string lengths.
-
- #define DO_STAT 0
-
- #if DO_STAT
- #include <statcount.H>
- static void Count(int sz)
- {
- static StatCount cnt("Distribution of string sizes", 0, 64, 4);
- cnt(sz);
- }
- #else
- #define Count(size)
- #endif
-
-
- // The following macros handle allocation of string memory, either with
- // the internal buffer of by allocating on the heap.
-
- #define allocate(str, n) str = n <= internal_buffer_size ? buf : new char[n]
- #define deallocate(str) if (str != buf) delete [] str
-
-
- // ----------------------------------------------------------------------------
- // Constructors, destructor
-
- String :: String ()
- {
- size = internal_buffer_size;
- allocate(str, internal_buffer_size);
- Count(size);
- str[0] = '\0';
- }
-
-
- String :: String (const char* s)
- {
- if (s == nil)
- s = "";
- size = max(strlen(s)+1, internal_buffer_size);
- allocate(str, size);
- Count(size);
- strcpy(str, s);
- }
-
-
- String :: String (const String& s)
- {
- size = s.Size();
- allocate(str, size);
- Count(size);
- strcpy(str, s.str);
- }
-
-
- String :: ~String()
- {
- deallocate(str);
- }
-
-
- // ----------------------------------------------------------------------------
- // Assignment, assignment operators
-
- String& String :: operator = (const String& s)
- {
- if (&s != this) { // same object?
- int len = s.Length();
- if (len >= size) {
- size = len + 1;
- deallocate(str);
- allocate(str, size);
- Count(size);
- }
- strcpy(str, s.str);
- }
- return *this;
- }
-
-
- String& String :: operator = (const char* s)
- // Note: works even if s == this->str, although "strcpy" is not needed.
- {
- if (s == nil)
- s = "";
-
- int len = strlen(s);
- if (len >= size) {
- size = len + 1;
- deallocate(str);
- allocate(str, size);
- Count(size);
- }
- strcpy(str, s);
-
- return *this;
- }
-
-
- String& String :: operator = (char c)
- {
- str[0] = c;
- str[1] = '\0';
- return *this;
- }
-
-
- void String :: operator += (const String& s)
- {
- unsigned newlen = Length() + s.Length();
- if (newlen < size)
- strcat(str, s.str);
- else {
- size = newlen + internal_buffer_size;
- char* r = new char[size];
- Count(size);
- strcpy(r, str);
- strcat(r, s.str);
- deallocate(str);
- str = r;
- }
- }
-
-
- void String :: operator += (char c)
- {
- const int chunk_size = internal_buffer_size;
-
- unsigned oldlength = Length();
- if (oldlength + 1 >= size) {
- size += chunk_size;
- char* r = new char[size];
- Count(size);
- strcpy(r, str);
- deallocate(str);
- str = r;
- }
- str[oldlength] = c;
- str[oldlength+1] = '\0';
- }
-
-
- String operator + (const String& s1, const String& s2)
- {
- String r = s1;
- r += s2;
- return r;
- }
-
-
- // ----------------------------------------------------------------------------
- // Subscripting
-
- char String :: operator () (unsigned i) const
- {
- if (i < Length())
- return str[i];
- else
- return '\0';
- }
-
-
- String String :: operator () (unsigned start, unsigned n) const
- {
- static char* r = 0; // temporary storage
- delete r;
-
- unsigned len = Length();
- if (start >= len)
- return "";
- n = min(n, len-start);
-
- r = new char[n + 1];
- strncpy(r, str+start, n);
- r[n] = 0;
- return r;
- }
-
-
- // ----------------------------------------------------------------------------
- // Comparisons
-
-
- boolean operator == (const String& s1, const char* s2)
- {
- if (s2 == nil)
- s2 = "";
- return s1.str[0] == s2[0] && strcmp(s1.str, s2) == 0;
- }
-
-
- boolean operator == (char* s1, const String& s2)
- {
- if (s1 == nil)
- s1 = "";
- return s1[0] == s2.str[0] && strcmp(s1, s2.str) == 0;
- }
-
-
- // ----------------------------------------------------------------------------
- // Misc. utility functions
-
-
- char* String :: Copy() const
- {
- char* s = new char[Length() + 1];
- strcpy(s, str);
- return s;
- }
-
-
- String String :: upper() const
- {
- String t = *this;
- register char* p = &t.str[t.Length()];
- while (--p >= t.str)
- if (islower(*p)) *p = toupper(*p);
- return t;
- }
-
-
- String String :: lower() const
- {
- String t = *this;
- register char* p = &t.str[t.Length()];
- while (--p >= t.str)
- if (isupper(*p)) *p = tolower(*p);
- return t;
- }
-
-
- unsigned String :: Hashval() const
- {
- register char* p = str;
- register unsigned h = 0;
- while (*p != 0)
- h += unsigned(*(p++));
- return h;
- }
-
-
- // ----------------------------------------------------------------------------
- // Input/output on streams
-
- ostream& operator << (ostream& o, const String& s)
- {
- o << s.str;
- return o;
- }
-
-
- istream& operator >> (istream& i, String& s)
- {
- char c;
- s = "";
-
- while (i.get(c) && isspace(c)) // skip to next word
- ;
- if (i) { // read a word
- do
- s += c;
- while (i.get(c) && !isspace(c));
- if (i)
- i.putback(c);
- }
- return i;
- }
-